package com.dingreading.cloud.soms.service.impl;

import com.dingreading.cloud.common.util.NepUtil;
import com.dingreading.cloud.common.util.PageUtil;
import com.dingreading.cloud.soms.dto.CaScheduleLessonDto;
import com.dingreading.cloud.soms.dto.CallMemberDto;
import com.dingreading.cloud.soms.entity.CaScheduleLesson;
import com.dingreading.cloud.soms.entity.table.CaScheduleLessonTableDef;
import com.dingreading.cloud.soms.mapper.CaScheduleLessonMapper;
import com.dingreading.cloud.soms.service.CaScheduleLessonService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.dingreading.cloud.soms.entity.table.CaCallNamesTableDef.caCallNames;


/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class CaScheduleLessonServiceImpl extends BaseServiceImpl<CaScheduleLessonMapper, CaScheduleLesson, CaScheduleLessonTableDef> implements CaScheduleLessonService {


    @Override
    protected CaScheduleLessonTableDef getTable() {
        return CaScheduleLessonTableDef.caScheduleLesson;
    }

    @Resource
    private CaScheduleLessonMapper scheduleLessonMapper;

    @Override
    public Page<CaScheduleLessonDto> pageListV3(
            PageUtil pageUtil, String corpUid, String storeUid, String keyword, Integer status, String scheduleUid, String lessonUid,
            Long classId, String className, Long roomId, String username, String projectUid, String beginDate, String endDate
    ) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(corpUid))
            condition.and(table.corpUid.eq(corpUid));
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.roomName.like(keyword)
                    .or(table.className.like(keyword))
                    .or(table.productName.like(keyword))
                    .or(table.teacherName.like(keyword))
            );
        if (null != status)
            condition.and(table.status.eq(status));
        if (null != scheduleUid)
            condition.and(table.scheduleUid.eq(scheduleUid));
        if (null != lessonUid)
            condition.and(table.lessonUid.eq(lessonUid));
        if (StringUtils.isNotBlank(className))
            condition.and(table.className.like(className));
        if (null != classId)
            condition.and(table.classId.eq(classId));
        if (null != roomId)
            condition.and(table.roomId.eq(roomId));
        if (StringUtils.isNotBlank(projectUid))
            condition.and(table.projectUid.eq(projectUid));
        if (StringUtils.isNotBlank(username))
            condition.and(table.usernames.like("," + username + ","));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.teachDate.between(beginDate, endDate));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.desc(), table.beginTime.asc());

        return getMapper().paginateAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, CaScheduleLessonDto.class);
    }


    @Override
    public List<CaScheduleLessonDto> calendarListV3(String corpUid, String storeUid, String keyword, Integer status, Long classId, Long roomId, String username, String projectUid, String beginDate, String endDate) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(corpUid))
            condition.and(table.corpUid.eq(corpUid));
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.roomName.like(keyword)
                    .or(table.className.like(keyword))
                    .or(table.productName.like(keyword))
            );
        if (null != status)
            condition.and(table.status.eq(status));
        if (null != classId)
            condition.and(table.classId.eq(classId));
        if (null != roomId)
            condition.and(table.roomId.eq(roomId));
        if (StringUtils.isNotBlank(projectUid))
            condition.and(table.projectUid.eq(projectUid));
        if (StringUtils.isNotBlank(username))
            condition.and(table.usernames.like("," + username + ","));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.teachDate.between(beginDate, endDate));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.asc(), table.beginTime.asc());

        return getMapper().selectListByQueryAs(wrapper, CaScheduleLessonDto.class);
    }

    @Override
    public List<CaScheduleLesson> getByStoreUid(String storeUid, String keyword, Integer status) {
        QueryCondition condition = table.storeUid.eq(storeUid);
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.roomName.like(keyword));
        if (null != status)
            condition.and(table.status.eq(status));

        return getMapper().selectListByCondition(condition);
    }

    @Override
    public long dropBean(String storeUid, String lessonUid) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.lessonUid.eq(lessonUid))
                .and(table.status.eq(0))
                .and(table.callTime.isNull());

        return getMapper().deleteByCondition(condition);
    }

    @Override
    public void dropByScheduleUid(String storeUid, String scheduleUid) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.scheduleUid.eq(scheduleUid))
                .and(table.status.in(-1, 0));
        getMapper().deleteByCondition(condition);
    }

    @Override
    public List<CaScheduleLesson> queryConflictLessonToClass(String corpUid, String storeUid, List<String> teachDates,
                                                             String beginTime, String endTime, Long classId) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.storeUid.eq(storeUid))
                .and(table.status.ne(-1));
        if (CollectionUtils.isNotEmpty(teachDates))
            condition.and(table.teachDate.in(teachDates));
        if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime)) {
//            String s = "((begin_time >'" + beginTime + "' AND begin_time < '" + endTime + "') or (end_time > '" + beginTime + "' AND begin_time < '" + endTime + "'))";
//            condition.and(s);
//            condition.and(table.beginTime.gt(beginTime).and(table.beginTime.lt(endTime)).or(table.endTime.gt(beginTime).and(table.beginTime.lt(endTime))));
            condition.and(table.beginTime.between(beginTime, endTime).or(table.endTime.between(beginTime, endTime)));
        }
        if (null != classId)
            condition.and(table.classId.eq(classId));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public List<CaScheduleLesson> queryConflictLessonToRooms(String corpUid, String storeUid, List<String> teachDates,
                                                             String beginTime, String endTime, List<Long> roomIds, String scheduleUid, String lessonUid) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.storeUid.eq(storeUid))
                .and(table.status.ne(-1));
        if (CollectionUtils.isNotEmpty(teachDates))
            condition.and(table.teachDate.in(teachDates));
        if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime)) {
//            condition.and(table.beginTime.gt(beginTime).and(table.beginTime.lt(endTime)).or(table.endTime.gt(beginTime).and(table.beginTime.lt(endTime))));
            condition.and(table.beginTime.between(beginTime, endTime).or(table.endTime.between(beginTime, endTime)));
        }
        if (StringUtils.isNotBlank(scheduleUid))
            condition.and(table.scheduleUid.ne(scheduleUid));
        if (StringUtils.isNotBlank(lessonUid))
            condition.and(table.lessonUid.ne(lessonUid));

        if (CollectionUtils.isNotEmpty(roomIds)) {
//            QueryCondition queryCondition = QueryCondition.createEmpty();
//            for (Long roomId : roomIds) {
//                queryCondition = queryCondition.and(table.roomId.eq(roomId));
//            }
//            condition.and(queryCondition);
            condition.and(table.roomId.in(roomIds));
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public List<CaScheduleLesson> queryConflictLessonToTeachers(String corpUid, String storeUid, List<String> teachDates, String beginTime, String endTime, List<String> usernames, String scheduleUid, String lessonUid) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.storeUid.eq(storeUid))
                .and(table.status.ne(-1));
        if (CollectionUtils.isNotEmpty(teachDates))
            condition.and(table.teachDate.in(teachDates));
        if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime)) {
//            condition.and(table.beginTime.gt(beginTime).and(table.beginTime.lt(endTime)).or(table.endTime.gt(beginTime).and(table.beginTime.lt(endTime))));
            condition.and(table.beginTime.between(beginTime, endTime).or(table.endTime.between(beginTime, endTime)));
        }
        if (StringUtils.isNotBlank(scheduleUid))
            condition.and(table.scheduleUid.ne(scheduleUid));
        if (StringUtils.isNotBlank(lessonUid))
            condition.and(table.lessonUid.ne(lessonUid));

        if (CollectionUtils.isNotEmpty(usernames)) {
            QueryCondition queryCondition = QueryCondition.createEmpty();
            for (String username : usernames) {
                queryCondition = queryCondition.or(table.usernames.like("," + username + ","));
            }
            condition.and(queryCondition);
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public void updateLessons(
            String corpUid, String storeUid, String scheduleUid,
            Long roomId, String roomUid, String roomName, String content, String usernames,
            String teacherUid, String teacherName, String uid, String fullName, String remark
    ) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.storeUid.eq(storeUid))
                .and(table.scheduleUid.eq(scheduleUid))
                .and(table.status.eq(0));

        UpdateChain.of(CaScheduleLesson.class)
                .set(table.roomId, roomId)
                .set(table.roomUid, roomUid)
                .set(table.roomName, roomName)
                .set(table.usernames, usernames)
                .set(table.teacherUid, teacherUid)
                .set(table.teacherName, teacherName)
                .set(table.content, content)
                .set(table.remark, remark)
                .set(table.lastStaffUid, uid)
                .set(table.lastStaffUid, fullName)
                .where(condition)
                .update();
    }

    @Override
    public CaScheduleLesson getLessonInfo(String storeUid, String lessonUid) {
        QueryCondition condition = table.lessonUid.eq(lessonUid);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public CaScheduleLessonDto getLessonDto(String storeUid, String lessonUid) {
        QueryCondition condition = table.lessonUid.eq(lessonUid);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition);
        return getMapper().selectOneByQueryAs(wrapper, CaScheduleLessonDto.class);
    }

    @Override
    public List<CaScheduleLessonDto> getLessonByUids(String storeUid, List<String> uids) {
        QueryCondition condition = table.lessonUid.in(uids)
                .and(table.storeUid.eq(storeUid));
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition);
        return getMapper().selectListByQueryAs(wrapper, CaScheduleLessonDto.class);
    }

    @Override
    public boolean haveClassId(String storeUid, Long classId, List<Integer> status) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.classId.eq(classId));
        if (CollectionUtils.isNotEmpty(status))
            condition.and(table.status.in(status));
        return exists(condition);
    }

    @Override
    public boolean haveClassroom(String storeUid, Long classroomId, List<Integer> status) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.roomId.eq(classroomId));
        if (CollectionUtils.isNotEmpty(status))
            condition.and(table.status.in(status));
        return exists(condition);
    }

    @Override
    public boolean callNames(
            String storeUid, String lessonUid, String teacherName,
            int reachNum, int lateNum, int askLeaveNum, int notReachNum, int noHourNum,
            Integer lessonStatus, String staffUid, String staffName, Date callTime
    ) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.lessonUid.eq(lessonUid))
                .and(table.status.ne(2));

        UpdateChain<CaScheduleLesson> updateChain = UpdateChain.of(CaScheduleLesson.class);
        updateChain.set(table.teacherName, teacherName)
                .set(table.reachNum, reachNum)
                .set(table.lateNum, lateNum)
                .set(table.askLeaveNum, askLeaveNum)
                .set(table.notReachNum, notReachNum)
                .set(table.noHourNum, noHourNum)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName));
        if (lessonStatus.equals(0)) {
            updateChain.set(table.status, 1)
                    .set(table.callTime, callTime);
        }
        return updateChain.where(condition).update();
    }

    @Override
    public void updateStudentNum(String storeUid, Long classId, int stuNum) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.classId.eq(classId))
                .and(table.status.in(0, 1));

        UpdateChain.of(CaScheduleLesson.class)
                .set(table.studentNum, stuNum)
                .where(condition)
                .update();
    }

    @Override
    public void updateStudentTempNum(String storeUid, String lessonUid, int stuNum) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.lessonUid.eq(lessonUid))
                .and(table.status.in(0, 1));

        UpdateChain.of(CaScheduleLesson.class)
                .set(table.studentTempNum, stuNum)
                .where(condition)
                .update();
    }

    @Override
    public Page<CaScheduleLessonDto> getMakeUpLessonsV2(
            PageUtil pageUtil, String storeUid, String lessonUid, String projectUid, String stageUid,
            Long classId, Long roomId, String username, String beginDate, String endDate
    ) {
        QueryCondition condition = table.lessonUid.ne(lessonUid)
                .and(table.projectUid.eq(projectUid))
                .and(table.stageUid.eq(stageUid))
                .and(table.status.eq(2))
                .and(table.notReachNum.gt(0).or(table.askLeaveNum.gt(0)));
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        if (null != classId)
            condition.and(table.classId.eq(classId));
        if (null != roomId)
            condition.and(table.roomId.eq(roomId));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.teachDate.between(beginDate, endDate));
        if (StringUtils.isNotBlank(username)) {
            QueryCondition queryCondition = caCallNames.status.eq(2)
                    .and(caCallNames.callStatus.in(3, 4))
                    .and(caCallNames.memberName.like(username));

            QueryWrapper wrapper = QueryWrapper.create().select(caCallNames.lessonUid)
                    .from(caCallNames)
                    .where(queryCondition);

            List<String> lessonUids = getMapper().selectListByQueryAs(wrapper, String.class);
            if (CollectionUtils.isNotEmpty(lessonUids))
                condition.and(table.teacherName.like(username).or(table.lessonUid.in(lessonUids)));
            else
                condition.and(table.teacherName.like(username));
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.desc());

        return getMapper().paginateAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, CaScheduleLessonDto.class);
    }

    @Override
    public boolean setOk(String storeUid, String lessonUid, String staffUid, String staffName, Date closeTime) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.lessonUid.eq(lessonUid))
                .and(table.status.eq(1))
                .and(table.callTime.isNotNull());

        return UpdateChain.of(CaScheduleLesson.class)
                .set(table.status, 2)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .set(table.closeStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.closeStaffName, NepUtil.nullToZero(staffName))
                .set(table.closeTime, closeTime)
                .where(condition)
                .update();
    }

    @Override
    public void setCancel(String corpUid, String lessonUid, String staffUid, String staffName) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.lessonUid.eq(lessonUid))
                .and(table.status.eq(0))
                .and(table.callTime.isNull());
        UpdateChain.of(CaScheduleLesson.class)
                .set(table.status, -1)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(condition)
                .update();
    }


    @Override
    public Page<CaScheduleLessonDto> getOkLessonDtoPageV3(
            PageUtil pageUtil, String corpUid, String storeUid, String className, String projectUid, String stageUid,
            Long roomId, String teacherUid, String beginDate, String endDate,
            int staffRole, String username
    ) {
        QueryCondition condition = table.status.eq(2);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        if (StringUtils.isNotBlank(className))
            condition.and(table.className.like(className));
        if (StringUtils.isNotBlank(projectUid))
            condition.and(table.projectUid.eq(projectUid));
        if (StringUtils.isNotBlank(stageUid))
            condition.and(table.stageUid.eq(stageUid));
        if (null != roomId)
            condition.and(table.roomId.eq(roomId));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.teachDate.between(beginDate, endDate));

        if (staffRole == 6) {
            // 员工是导读，只能看自己的记录
            if (StringUtils.isNotBlank(username)) {
                condition.and(table.teacherUid.eq(username));
            }
        } else {
            if (StringUtils.isNotBlank(teacherUid)) {
                condition.and(table.teacherUid.eq(teacherUid));
            }
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teachDate.desc(), table.beginTime.asc());

        return getMapper().paginateAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, CaScheduleLessonDto.class);
    }

    @Override
    public List<CaScheduleLesson> getOkLessonsV3(
            String storeUid, String className, String projectUid, String stageUid,
            Long roomId, String teacherUid, String beginDate, String endDate, String keyword
    ) {
        QueryCondition condition = table.status.eq(2);
        if (StringUtils.isNotBlank(teacherUid)) {
            condition.and(table.teacherUid.eq(teacherUid));
        } else {
            if (StringUtils.isNotBlank(storeUid))
                condition.and(table.storeUid.eq(storeUid));
        }
        if (StringUtils.isNotBlank(className))
            condition.and(table.className.like(className));
        if (StringUtils.isNotBlank(projectUid))
            condition.and(table.projectUid.eq(projectUid));
        if (StringUtils.isNotBlank(stageUid))
            condition.and(table.stageUid.eq(stageUid));
        if (null != roomId)
            condition.and(table.roomId.eq(roomId));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.teachDate.between(beginDate, endDate));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.roomName.like(keyword)
                    .or(table.className.like(keyword))
                    .or(table.productName.like(keyword))
                    .or(table.storeName.like(keyword))
                    .or(table.teacherName.like(keyword))
            );

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.teacherUid.asc(), table.teachDate.desc());

        return getMapper().selectListByQuery(wrapper);
    }


    @Override
    public List<CallMemberDto> getClassMemberAndCallMember(String storeUid, Long classId, String lessonUid) {
        List<CallMemberDto> list = null;
        if (classId != null && classId > 0) {
            list = scheduleLessonMapper.getClassMemberAndCallMemberByClassId(storeUid, classId, lessonUid);
        } else {
            // 快速创建的活动,没有社团id
            list = scheduleLessonMapper.getClassMemberAndCallMember(storeUid, lessonUid);
        }
        return list;
    }

    @Override
    public List<String> getMemberUidByClassMemberAndCallMember(String storeUid, Long classId, String lessonUid) {
        return scheduleLessonMapper.getMemberUidByClassMemberAndCallMember(storeUid, classId, lessonUid);
    }

    @Override
    public List<CaScheduleLesson> getTodayUseNotOk(String ymd, Long classId) {
        QueryCondition condition = table.teachDate.eq(ymd)
                .and(table.status.eq(1))
                .and(table.callTime.isNotNull());
        if (null != classId)
            condition.and(table.classId.eq(classId));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public boolean haveProjectUid(String storeUid, String projectUid) {
        QueryCondition condition = table.projectUid.eq(projectUid);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        return exists(condition);
    }

    @Override
    public boolean haveStageUid(String storeUid, String stageUid) {
        QueryCondition condition = table.stageUid.eq(stageUid);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        return exists(condition);
    }

    @Override
    public long getNotConductedCntByToday(String corpUid, String storeUid, String today) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.storeUid.eq(storeUid))
                .and(table.status.eq(0))
                .and(table.teachDate.gt(today));
        return getMapper().selectCountByCondition(condition);
    }

    @Override
    public List<CaScheduleLesson> listByStoreUidAndLessonUidIn(String storeUid, List<String> lessonUidList) {
        return getMapper().selectListByCondition(table.storeUid.eq(storeUid).and(table.lessonUid.in(lessonUidList)));
    }

}
